﻿using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using DiskUsage.CoreLib;
using DiskUsage.CoreLib.MessageBus;

namespace DiskUsage
{
    /// <summary>
    /// Interaction logic for DirectoryTreeView.xaml
    /// </summary>
    public partial class DirectoryTreeView : UserControl, IRefreshable
    {
        private DirectoryInfo m_gotoDirInfo;
        public event RoutedPropertyChangedEventHandler<object> SelectedItemChanged
        {
            add
            {
                m_treeView.SelectedItemChanged += value;
            }
            remove
            {
                m_treeView.SelectedItemChanged -= value;
            }
        }

        public DirectoryTreeView()
        {
            this.InitializeComponent();
            PopulateTree(null);
            MessageBus<RefreshMessage>.Instance.MessageRecieved += Instance_MessageRecieved;
            MessageBus<DirectoryChangedMessage>.Instance.MessageRecieved += Instance_MessageRecieved;
        }

        void Instance_MessageRecieved(object sender, MessageBusEventArgs<DirectoryChangedMessage> e)
        {
            GotoPath(e.Message.NewDir);
        }

        void Instance_MessageRecieved(object sender, MessageBusEventArgs<RefreshMessage> e)
        {
            Refresh();
        }

        private void PopulateTree(DirectoryInfo dirInfo)
        {
            m_treeView.ItemsSource = new Collection<DirectoryPresentationBase>() { new MyComputer() };
            GotoPath(dirInfo);
        }

        private void GotoPath(DirectoryInfo dirInfo)
        {
            m_gotoDirInfo = dirInfo;
            if (dirInfo != null)
            {
                TreeViewExpander.ExpandTreeViewItems<DirectoryPresentationBase>(IsNodeParentOf, m_treeView);
                TreeViewExpander.SelectTreeViewItems<DirectoryPresentationBase>(IsNodeParentOf, CanSelectNode, m_treeView);
            }
        }

        private bool IsNodeParentOf(DirectoryPresentationBase directory)
        {
            return (directory == null || m_gotoDirInfo == null) ? false : directory.IsParentOf(m_gotoDirInfo);
        }

        private bool CanSelectNode(TreeViewItem treeViewItem)
        {
            var dataContext = treeViewItem.DataContext as DirectoryPresentationBase;
            if (dataContext == null || dataContext.DirectoryInfo == null || m_gotoDirInfo == null)
                return false;
            else return dataContext.DirectoryInfo.FullName == m_gotoDirInfo.FullName;
        }

        public void Refresh()
        {
            PopulateTree(GetCurrentDirInfo());
        }

        private DirectoryInfo GetCurrentDirInfo()
        {
            DirectoryInfo dirInfo = null;
            try
            {
                var dataContext = m_treeView.SelectedValue as DirectoryPresentationBase;
                if (dataContext != null)
                {
                    dirInfo = dataContext.DirectoryInfo;
                }
            }
            catch
            {
                dirInfo = null;
            }
            return dirInfo;
        }

        private void TreeViewItem_MouseRightButtonDown(object sender, MouseEventArgs e)
        {
            TreeViewItem item = sender as TreeViewItem;
            if (item != null)
            {
                item.Focus();
                e.Handled = true;
            }
        }

        private void StackPanel_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            var dataContext = ((StackPanel)sender).DataContext;
            var item = m_treeView.ContainerFromItem(dataContext);
            if (item != null)
            {
                if (e.ClickCount == 2)
                    item.IsExpanded = !item.IsExpanded;
            }
        }

        private void CalculateSize_Click(object sender, RoutedEventArgs e)
        {
            var selectedItem = m_treeView.SelectedItem as DirectoryPresentationBase;
            DirectorySizeTreeCreator.CreateTree(selectedItem.DirectoryInfo.FullName);
            MessageBus<RefreshMessage>.Instance.SendMessage(this, new RefreshMessage());
        }

        private void Refresh_Click(object sender, RoutedEventArgs e)
        {
            MessageBus<RefreshMessage>.Instance.SendMessage(this, new RefreshMessage());
        }
    }
}